/*****************************************************************************
*
* CPE439
*
* Experiment 5.
*
* File: main.c
*
* Description: RTOS-based application that:
*				
*				Counts the number of SW7 button presses and sends the count
*				value to the seven-segment display.
*				The count value when the button is pressed should be queued
*				up and eventually displayed on the upper two digits of the
*				seven-segment display for approximately one second (the
*				queued items are removed from the queue at a rate of one
*				per second).
*
*				- Toggle LED2 each time there is a SW7 button press.
*				- Constantly display the current number of items on the
*				  queue on the lower two digits of the sevensegment display.
*				- Light LED4 anytime the queue is full; turn it off at all
*				  other times.
*				- Clear the upper and lower displays to zero (one digit 
*				  blank, the other digit zero) when the SW6 button is pressed.
*
* Target Device: ATmega32 on STK500 development board.
* 
* Hardware Setup: PORTA -> LEDS
*                 SPI -> SSEG DISPLAY
*
* Author: Kevin Casteel, Luis Castillo
*
* Revisions: v-1.0 (4/29/11)
*           
*			 
*
******************************************************************************/
#define F_CPU 3686400
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "hw_init.h"
#include "spi_sseg.h"

//- semaphore declaration
xSemaphoreHandle xMutex;
xSemaphoreHandle xBinary;

/*---------------------------------------------------------
* Function: main
*
* Description: Calls functions to initialize IO, creates
* tasks, and start the scheduler.
*
* return: 0 on success, non-zero value on failure.
*---------------------------------------------------------*/
int main( void )
{  	
    //- parameter declarations
/*    parameters_t task1, task2;
    task1.led = PIN0;
	task1.millisec = DELAY1;
	task2.led = PIN0;
	task2.millisec = DELAY2;
*/
	vIO_init(); 
	vINT0_init();
	//vSSEG_init();
	
	sei();

	//- create mutex semaphore
//	xMutex = xSemaphoreCreateMutex();

	//- create binary semaphore
	vSemaphoreCreateBinary(xBinary);

	//- Create tasks
//	xTaskCreate((pdTASK_CODE) vTaskFunction_1, (signed char *) "T1", 
//				configMINIMAL_STACK_SIZE, (void *) &task1, 1, NULL );

//	xTaskCreate((pdTASK_CODE) vTaskFunction_2, (signed char *) "T2", 
//				configMINIMAL_STACK_SIZE, (void *) &task2, 1, NULL );

	xTaskCreate(vHandlerTask, "Handler", 1000, NULL, 3, NULL );

    //- kick off the scheduler
	vTaskStartScheduler();

	return 0;
}


/*---------------------------------------------------------
* Function: vTaskFunction_1
*
* Description: Function performs the task. Toggles LED
* 			   specified by the pvParameters structure at a
*			   rate also designated by the same structure.
*
* parameter: pvParameters structure that contains the led
*			 and rate for it to be toggled.
*---------------------------------------------------------
void vTaskFunction_1(void *pvParameters)
{
   static uint8_t count = 0;
   parameters_t *val = (parameters_t *) pvParameters;

   //- infinite loop
   for (;;)  {
      PORTA ^= _BV(val->led); //- toggle led
	  count++;                //- count led transition
	  if(count > 99)          //- roll over at count 99
	  {
	  	count = 0;
	  }
	  //- protect SPI port
	  if(xSemaphoreTake(xMutex, 0)) //- take mutex
	  {
	    //- write count to sseg display
      	SSEG_Write_left_digits(count); 
		xSemaphoreGive(xMutex);     //- give mutex		
	  }
	  vTaskDelay(val->millisec/portTICK_RATE_MS);
   }
}
*/

/*---------------------------------------------------------
* Function: vTaskFunction_2
*
* Description: Function performs the task. Toggles LED
* 			   specified by the pvParameters structure at a
*			   rate also designated by the same structure.
*
* parameter: pvParameters structure that contains the led
*			 and rate for it to be toggled.
*---------------------------------------------------------
void vTaskFunction_2(void *pvParameters)
{
   static uint8_t count = 0;
   parameters_t *val = (parameters_t *) pvParameters; 

   for (;;)  {
      PORTA ^= _BV(val->led); //- toggle led
	  count++;                //- count led transition
	  if(count > 99)          //- roll over at count 99
	  {
	  	count = 0;
	  }
	  //- protect SPI port
	  if(xSemaphoreTake(xMutex, 0)) //- take mutex
	  {
	    //- write count to sseg display
      	SSEG_Write_right_digits(count);
		xSemaphoreGive(xMutex);	    //- give mutex	
	  }
	  vTaskDelay(val->millisec/portTICK_RATE_MS);
   }
}
*/

/*---------------------------------------------------------
* Function: vHandlerTask
*
* Description: Task handles data after an interrupt is
* 			   received. It also works as a mechanism to
*			   debounce SW7.
*---------------------------------------------------------*/
void vHandlerTask(){
   for( ;; )   {
      xSemaphoreTake(xBinary, portMAX_DELAY );
      PORTA ^= (_BV(PIN2) | _BV(PIN4));
   }
}

/*---------------------------------------------------------
* Function: ISR
*
* Description: Interrupt Service Routine for external
*			   interrupt INT0.
*
* parameter: INT0_vect external interrupt INT0 vector
*---------------------------------------------------------*/
ISR(INT0_vect)
{
    static portBASE_TYPE xHigherPriorityTaskWoken;
    xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR(xBinary, &xHigherPriorityTaskWoken);
}
